package com.aniu.portforwarder;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.StrictMode;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ForwardService extends Service {
    private final String TAG = "ForwardService";

    public ForwardService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();

        //解除StrictMode对网络的访问限制
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectDiskReads()
                .detectDiskWrites()
                .detectNetwork() // 这里可以替换为detectAll() 就包括了磁盘读写和网络I/O
                .penaltyLog() //打印logcat，当然也可以定位到dropbox，通过文件保存相应的log
                .build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedSqlLiteObjects() //探测SQLite数据库操作
                .penaltyLog() //打印logcat
                .penaltyDeath()
                .build());

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int port = Integer.parseInt(intent.getStringExtra(MainActivity.LOCAL_PORT));
        final String remotHost = intent.getStringExtra(MainActivity.REMOTE_HOST);
        int remotePort = Integer.parseInt(intent.getStringExtra(MainActivity.REMOTE_PORT));
        ServerSocket serverSocket = null;

        InputStream localInputStream = null;
        OutputStream localOutputStream = null;
        Socket forwardSocket = null;
        InputStream remoteInputStream = null;
        OutputStream remoteOutputStream = null;

        try {
            serverSocket = new ServerSocket(port, 100, null);
            Log.i(TAG, "Listening on port " + port);

            while (true) {
                Socket localSocket = serverSocket.accept();

                localInputStream = localSocket.getInputStream();
                localOutputStream = localSocket.getOutputStream();
                forwardSocket = new Socket(remotHost, remotePort);
                remoteInputStream = forwardSocket.getInputStream();
                remoteOutputStream = forwardSocket.getOutputStream();

                TunnelThread local2Remote = new TunnelThread(localInputStream, remoteOutputStream, "local -> remote");
                local2Remote.setDaemon(true);
                local2Remote.start();
                TunnelThread remote2Local = new TunnelThread(remoteInputStream, localOutputStream, "remote -> local");
                remote2Local.setDaemon(true);
                remote2Local.start();
            }
        } catch (Exception e){
            Log.e(TAG, "set up forward tunnel error", e);
        }

        //如果系统在 onStartCommand() 返回后终止服务，则其会重建服务，并通过传递给服务的最后一个 Intent 调用 onStartCommand()。
//        return super.onStartCommand(intent, flags, startId);
        return START_REDELIVER_INTENT;
    }

    private class TunnelThread extends Thread {
        private InputStream inputStream;
        private OutputStream outputStream;
        private String threadName;

        TunnelThread(InputStream inputStream, OutputStream outputStream, String threadName) {
            this.inputStream = inputStream;
            this.outputStream = outputStream;
            this.threadName = threadName;
        }

        public void run() {

            byte buffer[] = new byte[1024];
            int index;

            try {
                while ((index = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, index);
                    outputStream.flush();
                }
            } catch (IOException e) {
                Log.e(TAG, "write outstream error", e);
            } finally {
                try {
                    inputStream.close();
                    outputStream.close();
                } catch (IOException e) {
                    Log.e(TAG, "close input/output stream error", e);
                }
            }

            Log.i(TAG, threadName + " - finished ");
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
